#!/usr/bin/perl

use strict;
use warnings;
use lib 'lib';
use OpenID::Tester;
use LWP::UserAgent;
use Getopt::Long;

my $have_paranoid_agent;
BEGIN {
    $have_paranoid_agent = eval "use LWPx::ParanoidAgent; 1;";
}

my ($op_base, $rp_base, $base);
GetOptions(
	   "op_base=s" => \$op_base,
	   "rp_base=s" => \$rp_base,
           "base=s"    => \$base,
	   );

if ($base) {
    die "Don't specify --op_base with --base\n" if $op_base;
    die "Don't specify --rp_base with --base\n" if $rp_base;
    $op_base = $rp_base = $base;
}

unless ($op_base || $rp_base) {
    die "Usage: run-tests [--op_base=BASE_URL] [--rp_base=BASE_URL]\n";
}

my $ua;
if ($have_paranoid_agent) {
    $ua = LWPx::ParanoidAgent->new;
} else {
    $ua = LWP::UserAgent->new;
}

my $tester = OpenID::Tester->new(ua => $ua,
				 op_base => $op_base,
				 rp_base => $rp_base);

my @test_classes = qw(OPCaps
                      RPCaps
                      Canonicalize
                      Discovery
                      CheckID
                      );

my @passed;
my @failed;
my @skipped;

CLASS:
foreach my $partial_class (@test_classes) {
    print "$partial_class ...\n";
    my $class = "OpenID::Tester::Test::" . $partial_class;
    my $loaded = eval "use $class; 1;";
    unless ($loaded) {
        print " ... FAILED TO LOAD: $@\n";
        next;
    }

    my @tests = $class->tests($tester);
  TEST:
    foreach my $test (@tests) {
        my $summary = $test->summary;
        print "$summary\n" if $summary;

        # skip if no rp_base or op_base setup and test needs it
        if ($test->needs_rp) {
             if (! $rp_base) {
                print " ... skipped (no RP base configured)\n";
                skipped($test, "no RP base configured");
                next TEST;
            }
            foreach my $cap ($test->needed_rp_caps) {
                unless ($tester->has_rp_cap($cap)) {
                    skipped($test, "RP lacks capability '$cap'");
                    next TEST;
                }
            }
        }
        if ($test->needs_op) {
            if (! $op_base) {
                skipped($test, 'no OP base configured');
                next TEST;
            }
            foreach my $cap ($test->needed_op_caps) {
                unless ($tester->has_op_cap($cap)) {
                    skipped($test, "OP lacks capbility '$cap'");
                    next TEST;
                }
            }
         }

        my $results = eval { $test->run; } || "";
        if ($results) {
            passed($test);
        } else {
            my $errmsg = $@;
            $errmsg =~ s!\s+$!!;
            failed($test, $errmsg);
        }
    }
}

print "\n\n".scalar(@passed)." tests passed, while ".scalar(@failed)." failed and ".scalar(@skipped)." were skipped\n\n";

if (@failed) {
    print "Failed tests:\n";
    foreach my $result (@failed) {
        my ($test, $reason) = @$result;
        print " * ".$test->summary.": $reason\n";
    }

}

sub passed {
    my ($test) = @_;
    push @passed, [ $_[0] ];
    print " ... passed\n";
}
sub failed {
    my ($test, $reason) = @_;
    push @failed, [ $_[0], $reason ];
    print " ... FAILED ($reason)\n";
}
sub skipped {
    my ($test, $reason) = @_;
    push @skipped, [ $_[0], $reason ];
    print " ... skipped ($reason)\n";
}

